<template>
  <div>
    <a-upload
      v-bind="$attrs"
      v-model:file-list="fileList"
      :custom-request="customRequest"
      :show-upload-button="!(mergedDisabled || disabled)"
      :disabled="mergedDisabled || disabled"
      @before-upload="beforeUpload"
      @change="onChange"
      @preview="handlePreview"
    >
      <template v-for="(item, name) in $slots" :key="name" #[name]="dataObj">
        <slot :name="name" v-bind="dataObj || {}"></slot>
      </template>
    </a-upload>
  </div>
</template>

<script lang="ts" setup>
  import axios from 'axios';
  import { ref, withDefaults, defineEmits, defineProps, watch } from 'vue';
  import { Message, useFormItem } from '@arco-design/web-vue';
  import { apiUpload } from '@/api/common/index';
  import { isImage } from '@/utils/fileType';
  import ModalViewImage from '@/components/ModalViewImage';

  interface Props {
    modelValue: any[];
    disabled: boolean;
    maxSize: number;
  }
  const props = withDefaults(defineProps<Props>(), {
    disabled: false,
    maxSize: 0,
  });

  const emit = defineEmits(['change', 'update:modelValue']);
  const { mergedDisabled } = useFormItem();

  const fileList = ref<any[]>([]);

  const onChange = (val: any[], fileItem: any) => {
    if (fileItem.status === 'done') {
      const list = val
        .filter((t) => t.status === 'done')
        .map((t) => {
          return {
            ...t,
            resData: t?.response?.data || t.resData,
          };
        });
      emit('update:modelValue', list);
      emit('change', list);
    }
  };

  const customRequest: any = (opt: {
    onProgress: any;
    onError: any;
    onSuccess: any;
    fileItem: any;
    name: any;
  }) => {
    const { onError, onSuccess, fileItem, onProgress } = opt;
    const { CancelToken } = axios;
    let abort: any;

    const config = {
      onUploadProgress(event: any) {
        let percent: any;
        if (event.total > 0) {
          percent = (event.loaded / event.total) * 100;
        }
        onProgress(parseInt(percent, 10), event);
      },
      cancelToken: new CancelToken(function executor(c: any) {
        abort = c;
      }),
    };

    const formData = new FormData();
    formData.append('file', fileItem.file);
    apiUpload(formData, config)
      .then(({ code, message, data }) => {
        Message.success({
          content: '上传成功',
        });

        onSuccess({ code, message, data });
      })
      .catch((err) => {
        console.log(err, 'err');

        onError('上传失败');
      });

    return {
      abort,
    };
  };

  const beforeUpload = (file: File): Promise<boolean> => {
    return new Promise<boolean>((resolve, reject) => {
      const { size } = file;
      if (size / 1024 / 1024 > props.maxSize && props.maxSize > 0) {
        Message.error(`文件大小不能大于${props.maxSize}MB`);
        reject();
      }
      resolve(true);
    });
  };

  const handlePreview = (fileItem: any) => {
    const { url } = fileItem;

    if (isImage(url)) {
      ModalViewImage({
        imageList: props.modelValue,
        imageItemType: 'object',
        currentImg: url,
      });
    } else {
      window.open(url);
    }
  };

  watch(
    () => props.modelValue,
    (newVal) => {
      console.log('🚀 ~ newVal:', newVal);
      fileList.value = newVal || [];
    },
    {
      immediate: true,
      deep: true,
    }
  );
</script>

<style lang="less" scoped></style>
